package com.zsh.rabbitmq.springbootrabbitmq.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.ReturnedMessage;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

/**
 * @author zsh
 * @Description
 * @create 2022-05-07 17:01
 */
@Slf4j
@Component
public class MyCallBack implements RabbitTemplate.ConfirmCallback,RabbitTemplate.ReturnsCallback {

    //注入实现类
    @Resource
    private RabbitTemplate rabbitTemplate;

    @PostConstruct //顺序必须在rabbitTemplate之后
    public void init(){
        rabbitTemplate.setConfirmCallback(this);

        /**
         * true： * 交换机无法将消息进行路由时，会将该消息返回给生产者
         * false： * 如果发现消息无法进行路由，则直接丢弃
         */
        rabbitTemplate.setMandatory(true);
        //设置回退消息交给谁处理
        rabbitTemplate.setReturnsCallback(this);
    }

    //交换机确认回调方法
    /*
    1. 交换机收到消息，触发回调
        1.1 correlationData 保存回调消息Id及信息
        1.2 交换机收到消息ack = true
        1.3 cause null
    2. 交换机接收失败，触发回调
        2.1 correlationData 保存回调消息Id及信息
        2.2 交换机收到消息ack = false
        2.3 cause 未接收的原因
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {
        String id = correlationData != null ? correlationData.getId() : "";
        if (ack) {
            log.info("交换机已收到消息，id为：{}", id);
        } else {
            log.info("交换机未收到消息，id为：{}，原因是：{}", id,cause);
        }
    }

    //通过设置 mandatory 参数可以在当消息传递过程中不可达目的地时将消息返回给生产者。
    //只有失败来这
    @Override
    public void returnedMessage(ReturnedMessage returnedMessage) {
        log.info("消息{}，被交换机{}退回，退回原因{}，路由Key{}",
                new String(returnedMessage.getMessage().getBody()),
                returnedMessage.getExchange(),
                returnedMessage.getReplyText(),
                returnedMessage.getRoutingKey());


    }
}
